package cn.livingCloud.service.impl;

import cn.livingCloud.context.SessionConstants;
import cn.livingCloud.dto.EmployeeAccountDto;
import cn.livingCloud.dto.EmployeeAccountFormDto;
import cn.livingCloud.dto.EmployeeAccountListDto;
import cn.livingCloud.dto.EmployeeDto;
import cn.livingCloud.entity.core.Employee;
import cn.livingCloud.entity.core.EmployeeAccount;
import cn.livingCloud.entity.system.Setting;
import cn.livingCloud.entity.user.AccountPrivilege;
import cn.livingCloud.entity.user.Member;
import cn.livingCloud.entity.user.Privilege;
import cn.livingCloud.entity.user.UserAccount;
import cn.livingCloud.repository.*;
import cn.livingCloud.service.EmployeeAccountService;
import cn.livingCloud.utils.SessionUtils;
import cn.livingCloud.wechat.handler.WechatUserInfoHandler;
import cn.livingCloud.wechat.protocol.WechatUserInfo;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Collection;
import java.util.List;

/**
 * Created by 唐旭 on 2016/5/30.
 */
@Service
public class EmployeeAccountServiceImpl extends UserAccountServiceImpl implements EmployeeAccountService {
    @Autowired
    private EmployeeAccountMapper mapper;
    @Autowired
    private UserAccountMapper userAccountMapper;
    @Autowired
    private EmployeeMapper employeeMapper;
    @Autowired
    private AccountPrivilegeMapper privilegeMapper;
    @Autowired
    private SettingMapper settingMapper;
    @Autowired
    private MemberMapper memberMapper;

    @Override
    public AuthenticationInfo login(String username, String password) {
        EmployeeAccount account = mapper.findAccountByUserNamePassword(username, password);
        if (StringUtils.isEmpty(account.getEmployeeUuid())) {
            return super.login(username, password);
        }

        return account.login();
    }

    @Override
    public AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals, SimpleAuthorizationInfo info) {
        Collection collection = principals.fromRealm(UserAccount.REALM_NAME);
        if (collection != null && !collection.isEmpty()) {
            return super.doGetAuthorizationInfo(principals, info);
        }
        String memberUuid = (String) principals.fromRealm(Member.MEMBER_REALM).iterator().next();
        Employee employee = employeeMapper.findEmployeeByMember(memberUuid);
        //如果用户没有绑定微信
        if (employee == null) {
            return info;
        }
        List<UserAccount> accountList = mapper.findAccountListByEmployee(employee.getUuid());
        for (UserAccount account : accountList) {
            addPrivilege(account, info);
        }

        return info;
    }

    @Override
    public AuthenticationInfo loginMember(String memberCode) {
        Setting setting = settingMapper.findSetting();
        WechatUserInfo userInfo = new WechatUserInfoHandler()
                .getUserInfo(memberCode, setting.getAppid(), setting.getSecret());

        if (StringUtils.isEmpty(userInfo.getOpenid())) {
            return null;
        }

        Member member = memberMapper.findMemberByOpenid(userInfo.getOpenid());
        if (member == null) {
            member = new Member(userInfo);
            memberMapper.save(member);
        }
        SimpleAuthenticationInfo result = new SimpleAuthenticationInfo(member.toString(), memberCode, Member.MEMBER_REALM);
        SessionUtils.setAttribute(SessionConstants.MEMBER_KEY, member);
        SessionUtils.setAttribute(SessionConstants.EMPLOYEE_KEY, employeeMapper.findEmployeeByMember(member.getUuid()));

        return result;
    }

    @Override
    public void loadList(EmployeeAccountListDto listDto) {
        String deptUuid = listDto.getDeptUuid();
        if (StringUtils.isEmpty(deptUuid)) {
            Employee employee = SessionUtils.getAttribute(Employee.class, SessionConstants.EMPLOYEE_KEY);
            if (employee != null) {
                listDto.setDeptUuid(employee.getDeptUuid());
            }
        }
        List<EmployeeAccount> list = mapper.getList(listDto);
        listDto.addAllList(list);
    }

    @Override
    public EmployeeAccountDto updateState(String uuid, boolean state) {
        EmployeeAccount userAccount = mapper.selectByPrimaryKey(uuid);
        //如果前台传入执行的状态和数据库的状态相同那么就异常
        if (state == userAccount.isEnable()) {
            throw new IllegalStateException("禁用/启用失败,请检查账号状态是否被禁用/启用!");
        }
        //如果前台的状态和数据库的状态不相同那么就执行当前传入的操作
        userAccount.setEnable(state);
        userAccountMapper.updateEnable(userAccount);
        EmployeeAccountDto employeeAccountDto = new EmployeeAccountDto(userAccount);
        Employee employee = employeeMapper.selectByPrimaryKey(userAccount.getEmployeeUuid());
        employeeAccountDto.setEmployeeDto(new EmployeeDto(employee));
        return employeeAccountDto;
    }

    @Override
    public EmployeeAccountFormDto loadEmployeeAccountForm(String uuid, String employeeUuid) {
        EmployeeAccountFormDto formDto;

        if (StringUtils.isNotEmpty(uuid)) {
            EmployeeAccount account = mapper.selectByPrimaryKey(uuid);
            formDto = new EmployeeAccountFormDto(account);
        } else {
            formDto = new EmployeeAccountFormDto();
            if (StringUtils.isNotEmpty(employeeUuid)) {
                Employee employee = employeeMapper.selectByPrimaryKey(employeeUuid);
                formDto.setEmployeeDto(new EmployeeDto(employee));
                formDto.setEmployeeUuid(employeeUuid);
            }
        }

        UserAccount attribute = SessionUtils.getAttribute(UserAccount.class, SessionConstants.USER_ACCOUNT_KEY);
        List<AccountPrivilege> privilegeList = attribute.getPrivilegeList();
        List<Privilege> privileges = formDto.getCurrentPrivileges();
        privileges.clear();
        for (AccountPrivilege accountPrivilege : privilegeList) {
            Privilege privilege = accountPrivilege.getPrivilege();
            if (privilege.isEmployee()) {
                privileges.add(privilege);
            }
        }

        return formDto;
    }

    @Override
    public void updateEmployeeAccount(EmployeeAccountFormDto formDto) {
        EmployeeAccount account;
        if (StringUtils.isEmpty(formDto.getUuid())) {
            account = new EmployeeAccount();
            formDto.updateEmployeeAccount(account);
            mapper.insert(account);
        } else {
            account = mapper.selectByPrimaryKey(formDto.getUuid());
        }

        privilegeMapper.deleteAccountPrivilege(account.getUuid());
        AccountPrivilege accountPrivilege;
        List<AccountPrivilege> privileges = account.getPrivilegeList();
        privileges.clear();

        List<Privilege> privilegeList = formDto.getPrivilegeList();
        for (Privilege privilege : privilegeList) {
            accountPrivilege = new AccountPrivilege()
                    .setUserAccountId(account.getUuid())
                    .setPrivilege(privilege);
            privileges.add(accountPrivilege);
        }
        if (privileges.size() > 0) {
            privilegeMapper.insertList(privileges);
        }
    }
}
